package com.tang.logger.pusher;

import com.tang.logger.config.LogPusherProperties;
import com.tang.logger.domain.LogMessage;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Tang
 * @classname MultiplexLogPusher
 * @description [  ]
 * @date 2021/7/25 22:06
 */
@Component
public class MultiplexLogPusher implements LogPusher, InitializingBean {

    @Resource
    ApplicationContext applicationContext;

    private List<LogPusher> logPusherList;

    private ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1, 100, TimeUnit.MILLISECONDS,
            new SynchronousQueue<>(), new CustomizableThreadFactory("log-pusher-multiplex-"));


    @Override
    public void push(LogMessage logMessage) {
        logPusherList.forEach(logPusher -> { logPusher.push(logMessage); });
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initLogPusherList();
        singleThreadPool.execute(this::pushLogEventLoop);
    }

    /**
     * 初始化 log pusher list
     */
    private void initLogPusherList() {
        logPusherList = applicationContext.getBeanProvider(LogPusher.class).stream()
                .collect(Collectors.toList());
    }

    /**
     * 日志推送死循环
     */
    private void pushLogEventLoop() {
        try {
            while (true) {
                LogMessage logMessage = LogMessageBuffer.take();
                this.push(logMessage);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}